
local ggf = require('GGE.函数')
local SDL = require 'SDL'
local 地图寻路 = require('地图/寻路')
local 地图类 = class('地图', 地图寻路)
local function 排序(a,b) return a.xy.y < b.xy.y end
local tdt = 0
local insert = table.insert
local remove = table.remove
function 地图类:初始化(id,当前)
    local map = assert(__res:取地图('scene/'..id..'.map'), '地图不存在')
    --打开地图
    self.map = map
    self.id = id
    self.宽度 = map.width
    self.高度 = map.height
    self.列数 = map.colnum
    self.行数 = map.rownum
    self.块宽度 = 320
    self.块高度 = 240
    self.当前=当前
    self:置宽高()
    self.co = {}
    self.对象数据 = {}
    --__res:地图音乐(id)
    --==================================================================================
    self.info = {}
    local n = 1
    for y = 1, self.行数 do
        self.info[y] = {}
        for x = 1, self.列数 do
            self.info[y][x] = {
                xy = require('GGE.坐标')((x) * self.块宽度, (y - 1) * self.块高度), --地表所在坐标
                id = n --地表的号码
                --_id = __f14:置颜色(255,255,255,255):取描边精灵(n)
            }
            n = n + 1
        end
    end
    --==================================================================================
    地图寻路.地图寻路(self, self.列数 * 16, self.行数 * 12, map:取障碍())
    --==================================================================================

    self.对象 = {}

    --地表显示范围
    self.a = require('GGE.坐标')(1, 1)
    self.b = require('GGE.坐标')(1, 1)
    map:更新()
end

function 地图类:加载(id)
    --local map = assert(__res:取地图('scene/1400.map'), '地图不存在')
    local map = assert(__res:取地图('scene/'..id..'.map'), '地图不存在')
    --打开地图
    self.map = map
    self.id = id
    self.宽度 = map.width
    self.高度 = map.height
    self.列数 = map.colnum
    self.行数 = map.rownum
    self.块宽度 = 320
    self.块高度 = 240

    self:置宽高()

    --__res:地图音乐(id)
    --==================================================================================
    self.info = {}
    local n = 1
    for y = 1, self.行数 do
        self.info[y] = {}
        for x = 1, self.列数 do
            self.info[y][x] = {
                xy = require('GGE.坐标')((x) * self.块宽度, (y - 1) * self.块高度), --地表所在坐标
                id = n --地表的号码
                --_id = __f14:置颜色(255,255,255,255):取描边精灵(n)
            }
            n = n + 1
        end
    end
    --==================================================================================
    地图寻路.地图寻路(self, self.列数 * 16, self.行数 * 12, map:取障碍())
    --==================================================================================

    self.对象 = {}

    --地表显示范围
    self.a = require('GGE.坐标')(1, 1)
    self.b = require('GGE.坐标')(1, 1)
end

function 地图类:置宽高(w, h)
    self.屏幕列数 = math.ceil(引擎.宽度 / 320)
    self.屏幕列数2 = self.列数 - self.屏幕列数
    self.屏幕列数3 = math.ceil(self.屏幕列数 / 2)
    self.屏幕行数 = math.ceil(引擎.高度 / 240)
    self.屏幕行数2 = self.行数 - self.屏幕行数
    self.屏幕行数3 = math.ceil(self.屏幕行数 / 2)
end


local _协程载入 = function(self, t)
    t.精灵, t.遮罩 = self.map:取精灵(t.id) --返回地表和附近的遮罩
end

function 地图类:更新(dt, pos, obj) --_,屏幕中心,显示队列
    self.map:更新()
    local _加入显示 = ggf.insert(obj)
    if self.当前 == 多开数据.当前 then
        if pos.x < self.屏幕列数 then --左
            self.a.x = 1
            self.b.x = self.屏幕列数 + 1
        elseif pos.x > self.屏幕列数2 then --右
            self.a.x = self.列数 - self.屏幕列数 - 1
            self.b.x = self.列数
        else
            self.a.x = pos.x - self.屏幕列数3
            self.b.x = pos.x + self.屏幕列数3
        end

        if pos.y < self.屏幕行数 then
            self.a.y = 1
            self.b.y = self.屏幕行数 + 1
        elseif pos.y > self.屏幕行数2 then
            self.a.y = self.行数 - self.屏幕行数 - 1
            self.b.y = self.行数
        else
            self.a.y = pos.y - self.屏幕行数3
            self.b.y = pos.y + self.屏幕行数3
        end

        local 重复遮罩 = {}
        --避免重复

        for y = self.a.y, self.b.y do
            for x = self.a.x, self.b.x do
                local t = self.info[y] and self.info[y][x]
                if t then
                    if __res.配置.关闭遮罩 == 1 then
                        if not t.精灵 and not t.load then
                            t.精灵, t.遮罩 = self.map:取精灵(t.id)
                            t.load = true
                        end
                    else
                        if not t.精灵 and not t.load then
                            -- t.精灵, t.遮罩 = self.map:取精灵(t.id)
                            t.load = true
                            coroutine.xpcall(_协程载入, self, t)
                        end
                        if t.遮罩 then
                            for _, v in ipairs(t.遮罩) do
                                if v and not 重复遮罩[v.id] then --其它地表可能拥有相同的遮罩，排除
                                    重复遮罩[v.id] = true
                                    --coroutine.xpcall(_协程载入, self, t)
                                    if 多开数据[self.当前].__主显.主角.飞行 ~= 1 then
                                        _加入显示(v)
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end
    for i, v in pairs(self.对象) do
        if not 多开数据[self.当前].__主控.战斗中 and (多开数据[self.当前].__主显.主角.xy:取距离(v.xy) < 450 or v.是否移动) then
            v:更新(dt)
            _加入显示(v)
        end
    end
    self.map:更新()
    -- if self.对象数据[1] then
    --     self:线程事件(self.对象数据[1],self.对象数据[1].pid)
    -- end
end

-- local 障碍 = require("SDL.精灵")(0,0,0,20,20):置颜色(0,0,0,255)
-- local 路径 = require("SDL.精灵")(0,0,0,20,20):置颜色(0,255,0,255)
-- 格子 = require("GGE.坐标")(20,20)
function 地图类:显示(xy)
    table.sort(多开数据[self.当前].__主显.显示表,排序)
    for y = self.a.y, self.b.y do
        for x = self.a.x, self.b.x do
            local t = self.info[y] and self.info[y][x]
            if t and t.精灵 then
                t.精灵:显示(t.xy + xy)
                -- t.精灵:显示矩形(255,255,0,255)
                -- --t._id:显示(t.xy + xy)
                -- local p = t.xy:复制()
                -- for py=1,12 do
                --     for px=1,16 do
                --         if not self:检查点(p.x//20,p.y//20) then
                --             障碍:显示(p + xy)
                --         end

                --         p.x = p.x+20
                --     end
                --     p.x = p.x-self.块宽度
                --     p.y = p.y+20
                -- end
            end
        end
    end
    for i=1,#多开数据[self.当前].__主显.显示表 do
        self:飞行处理(多开数据[self.当前].__主显.显示表[i])
        多开数据[self.当前].__主显.显示表[i]:显示(xy)
    end
    -- if 多开数据[self.当前].__主控.给予操作 or 多开数据[self.当前].__主控.队伍操作 then
    --     多开数据[self.当前].__主控.黑色背景:显示(0,0)
    -- end
    -- for i,v in ipairs(self._p) do
    --     v = require("GGE.坐标")(v.x,v.y)
    --     路径:显示(v + xy)
    -- end
end

function 地图类:添加对象数据(v)
    for i=1,#self.对象数据 do
        local x,y = v.x or v.X,v.y or v.Y
        local xx,yy = self.对象数据[i].x or self.对象数据[i].X,self.对象数据[i].y or self.对象数据[i].Y
        if 多开数据[self.当前].__主显.主角.xy:取距离(x,y)  < 多开数据[self.当前].__主显.主角.xy:取距离(xx,yy) then
            insert(self.对象数据,i,v)
            return
        end
    end
    insert(self.对象数据,v)
end


function 地图类:飞行处理(t)
    if t.飞行 == 1 and  t.飞行高度.y < 60 then
        t.飞行高度.y = t.飞行高度.y + 2
    elseif t.飞行 == 2 and t.飞行高度.y > 0 then
        t.飞行高度.y = t.飞行高度.y - 2
        if t.飞行高度.y < 0 then t.飞行高度.y  = 0 end
    end
end


function 地图类:协程加载对象(t)
    local co, main = coroutine.running()
    if not main then
        self.co[t.pid] = co
        return coroutine.yield()
    end
end

function 地图类:线程事件(t,i)
    if self.co[t.pid] then
        coroutine.resume(self.co[t.pid], self:添加对象(t))
    end
    self.co[t.pid] = nil
    remove(self.对象数据,1)
end

function 地图类:添加对象(t)
    if ggetype(t) == '主角' then
        self.对象[t.pid] = t
        return
    end
    if t.type == 0 then
        self.对象[t.pid] = require('对象/玩家')(t,self.当前)
    elseif t.type == 1 then
        self.对象[t.pid] = require('对象/召唤')(t,self.当前)
    elseif t.type == 2 then
        self.对象[t.pid] = require('对象/NPC')(t,self.当前)
    elseif t.type == 3 then
        self.对象[t.pid] = require('对象/跳转')(t,self.当前)
    elseif t.type == 4 then
        self.对象[t.pid] = require('对象/怪物')(t,self.当前)
    elseif t.type == 5 then
        self.对象[t.pid] = require('对象/物品')(t,self.当前)
    end
end

function 地图类:取重叠数据(x,y,pid)
    local 重叠数据 = {}
    for i,v in pairs(self.对象) do
        if v.type == 2 then
            local xx,yy = v.x or v.X,v.y or v.Y
            if 取两点距离({x=x,y=y},{x=xx,y=yy}) < 2 then
                重叠数据[#重叠数据+1] = v
            end
        end
    end
    return 重叠数据
end

function 地图类:更改对象(t)
    if not self.对象[t.pid] then
        return
    end
    self.对象[t.pid] = nil
    self:添加对象(t)
end

function 地图类:更改模型(t)
    if not self.对象[t.pid] then
        return
    end
    self.对象[t.pid]:更改模型(t)
end

function 地图类:删除对象(id)
    self.对象[id] = nil
end

function 地图类:取对象(id)
    return id and self.对象[id]
end

function 地图类:遍历对象()
    return next, self.对象
end

return 地图类
